<template>
  <div class="main">
    <!-- 画笔控件 用来拍照 -->
    <canvas style="display: none;width: 543px;height: 500px" ref="canvasDom"></canvas>
    <!-- 播放器，用来播放拍摄的视频 -->
    <video v-if="!imgurl" class="camera_video" ref="videoDom"></video>
    <!--  显示照片  -->
    <img style="width: 543px;height: 500px" v-else :src="imgurl" />

    <div class="divider"></div>
    <br />
    <!-- <el-button type="success" @click="takePhoto">{{ imgurl ? "重拍" : "拍照" }}</el-button> -->
  </div>
</template>

<script setup lang="ts">
  import { useUpload } from '@/components/UploadFile/src/useUpload'
  import { UploadRequestOptions } from 'element-plus/es/components/upload/src/upload'
  // 接受 props
  let props = defineProps(["modelValue"]);
  let $emit = defineEmits(['update:modelValue']);
  import { ref, onMounted } from "vue";

  // canvas 控件对象
  const canvasDom = ref(null);
  // video 控件对象
  const videoDom = ref(null);
  // 照片路径
  const imgurl = ref(null);

  const openCamera = () => {
    // 检测浏览器是否支持 mediaDevices
    if (navigator.mediaDevices) {
      navigator.mediaDevices
        // 开启视频，关闭音频
        .getUserMedia({
          audio: false, video: {
            width: { ideal: 543 }, // 期望宽度
            height: { ideal: 500 } // 期望高度
          }
        })
        .then((stream) => {
          // 将视频流传入 viedo 控件
          videoDom.value.srcObject = stream;
          // 播放
          videoDom.value.play();
        })
        .catch((err) => {
          console.log(err);
        });
    } else {
      window.alert("该浏览器不支持开启摄像头，请更换最新版浏览器");
    }
  };

  // 将 base64 转换为 Blob 对象
  const base64ToBlob = (base64) => {
    // 强制设置 content type 为 image/png
    const contentType = 'image/png';
    const parts = base64.split(';base64,');
    const raw = window.atob(parts[1]);
    const rawLength = raw.length;
    const uInt8Array = new Uint8Array(rawLength);

    for (let i = 0; i < rawLength; ++i) {
      uInt8Array[i] = raw.charCodeAt(i);
    }

    return new Blob([uInt8Array], { type: contentType });
  };

  // 上传图片到服务器
  const uploadImage = async (base64) => {
    const blob = base64ToBlob(base64);
    const formData = new FormData();
    formData.append('image', blob, 'photo.jpg');
    try {

      const { httpRequest } = useUpload()
      const photo = ((await httpRequest({
        file: blob,
        filename: 'photo.png',
      } as UploadRequestOptions)) as unknown as { data: string }).data
      return photo;
    } catch (error) {
      console.error('拍照失败:', error);
      return null;
    }
  };

  // 拍照
  const takePhoto = async (afterPicUrl) => {
    // 如果已经拍照了就重新启动摄像头
    if (afterPicUrl) {
      imgurl.value = null;
      openCamera()
      return;
    }
    canvasDom.value.width = videoDom.value.videoWidth;
    canvasDom.value.height = videoDom.value.videoHeight;

    // 执行画的操作
    canvasDom.value.getContext("2d").drawImage(videoDom.value, 0, 0);
    // 将结果转换为可展示的格式
    const base64Img = canvasDom.value.toDataURL("image/png");

    // 上传图片到服务器
    const networkImgUrl = await uploadImage(base64Img);
    if (networkImgUrl) {
      imgurl.value = networkImgUrl;
      $emit('update:modelValue', networkImgUrl);
    }

    // 关闭摄像头
    stop();
  }

  // 关闭摄像头
  const stop = () => {
    let stream = videoDom.value.srcObject;
    if (!stream) return;
    let tracks = stream.getTracks();
    tracks.forEach((x) => {
      x.stop();
    });
  };

  // 打开摄像头
  onMounted(() => {
    openCamera();
  });

  defineExpose({ takePhoto }) // 提供 open 方法，用于打开弹窗
</script>

<style scoped>
  .main {
    position: relative;
    display: flex;
    width: 543px;
    height: 500px;
    margin: 20px auto;
    flex-direction: column;
    justify-content: center;
    align-items: flex-end;
  }

  .camera_video {
    width: 100%;
    height: 100%;

    /* 移除边框 */
    border: none;

    /* 确保视频内容填满容器 */
    object-fit: cover;
  }

  .divider {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 50%;
    width: 1px;
    height: 100%;
    margin-top: -24px;

    /* 分割线宽度 */
    background-color: white;

    /* 分割线颜色 */
    transform: translateX(-50%);
    box-shadow: 0 0 5px rgb(0 0 0 / 50%);

    /* 添加阴影，增强视觉效果 */
  }
</style>